package com.piggy.logi.sys.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.piggy.common.core.exception.GlobalException;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.utils.sql.SqlUtil;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.logi.sys.bo.LogiMarginAddBo;
import com.piggy.logi.sys.bo.LogiMarginEditBo;
import com.piggy.logi.sys.bo.LogiMarginQueryBo;
import com.piggy.logi.sys.bo.LogiMarginUserQueryBo;
import com.piggy.logi.sys.domain.LogiCarrier;
import com.piggy.logi.sys.domain.LogiCarrierDriver;
import com.piggy.logi.sys.domain.LogiCustomer;
import com.piggy.logi.sys.domain.LogiMargin;
import com.piggy.logi.sys.enums.MarginFundStatusEnum;
import com.piggy.logi.sys.enums.MarginPayStatusEnum;
import com.piggy.logi.sys.enums.MarginTypeEnum;
import com.piggy.logi.sys.enums.MarginUserTypeEnum;
import com.piggy.logi.sys.mapper.LogiMarginMapper;
import com.piggy.logi.sys.service.ILogiCarrierDriverService;
import com.piggy.logi.sys.service.ILogiCarrierService;
import com.piggy.logi.sys.service.ILogiCustomerService;
import com.piggy.logi.sys.service.ILogiMarginService;
import com.piggy.logi.sys.vo.LogiMarginUserVo;
import com.piggy.logi.sys.vo.LogiMarginVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 保证金Service业务层处理
 *
 * @author fengxy
 * @date 2023/10/17 21:54
 **/
@Slf4j
@Service
public class LogiMarginServiceImpl extends ServiceImpl<LogiMarginMapper, LogiMargin> implements ILogiMarginService {

    @Resource
    private ILogiCustomerService logiCustomerService;

    @Resource
    private ILogiCarrierService logiCarrierService;

    @Resource
    private ILogiCarrierDriverService logiCarrierDriverService;

    @Override
    public TableDataInfo<LogiMarginVo> queryPageList(LogiMarginQueryBo bo) {
        PagePlus<LogiMargin, LogiMarginVo> pageVo = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiMarginVo.class);
        pageVo.getRecordsVo().forEach(this::fillData);
        return PageUtils.buildDataInfo(pageVo);
    }

    @Override
    public LogiMarginVo queryById(Long id) {
        LogiMarginVo marginVo = getVoById(id, LogiMarginVo.class);
        if (ObjectUtil.isNull(marginVo)) {
            throw new GlobalException("保证金不存在");
        }
        fillData(marginVo);
        return marginVo;
    }

    @Override
    public void insertByAddBo(LogiMarginAddBo bo) {
        LogiMargin margin = new LogiMargin();
        margin.setDeptId(bo.getDeptId());
        margin.setUserId(bo.getUserId());
        margin.setUserType(bo.getUserType());
        margin.setFundStatus(MarginFundStatusEnum.NORMAL.getCode());
        margin.setPayStatus(MarginPayStatusEnum.PAYED.getCode());
        margin.setType(MarginTypeEnum.USER.getCode());
        margin.setPayAccount(bo.getPayAccount());
        margin.setPayAccountType(bo.getPayAccountType());
        margin.setPayAmount(bo.getPayAmount());
        margin.setPayChannel(bo.getPayChannel());
        margin.setPayTime(bo.getPayTime());
        margin.setPayVoucher(bo.getPayVoucher());
        margin.setPayRemark(bo.getPayRemark());
        save(margin);
    }

    @Override
    public void refund(LogiMarginEditBo bo) {
        // 查询保证金详情
        LogiMarginVo marginVo = queryById(bo.getId());
        // 判断保证金的资金状态，如果是冻结则不允许操作
        if (marginVo.getFundStatus() == MarginFundStatusEnum.FREEZE.getCode()) {
            throw new GlobalException("请选择资金状态为正常的保证金");
        }
        // 修改保证金的资金状态为：冻结
        boolean success = update(Wrappers.lambdaUpdate(LogiMargin.class)
                .set(LogiMargin::getPayStatus, MarginPayStatusEnum.REFUND.getCode())
                .set(LogiMargin::getRefundAccount, bo.getRefundAccount())
                .set(LogiMargin::getRefundAccountType, bo.getRefundAccountType())
                .set(LogiMargin::getRefundAmount, bo.getRefundAmount())
                .set(LogiMargin::getRefundChannel, bo.getRefundChannel())
                .set(LogiMargin::getRefundTime, bo.getRefundTime())
                .set(LogiMargin::getRefundVoucher, bo.getRefundVoucher())
                .set(LogiMargin::getRefundRemark, bo.getRefundRemark())
                .eq(LogiMargin::getId, marginVo.getId()));
        if (!success) {
            throw new GlobalException("退回保证金失败，请联系管理员");
        }
    }

    @Override
    public void freeze(Long id) {
        // 查询保证金详情
        LogiMarginVo marginVo = queryById(id);
        // 判断保证金的资金状态，如果是冻结则不允许操作
        if (marginVo.getFundStatus() == MarginFundStatusEnum.FREEZE.getCode()) {
            throw new GlobalException("请选择资金状态为正常的保证金");
        }
        // 修改保证金的资金状态为：冻结
        boolean success = update(Wrappers.lambdaUpdate(LogiMargin.class)
                .set(LogiMargin::getFundStatus, MarginFundStatusEnum.FREEZE.getCode())
                .eq(LogiMargin::getId, marginVo.getId()));
        if (!success) {
            throw new GlobalException("冻结保证金失败，请联系管理员");
        }
    }

    @Override
    public void thaw(Long id) {
        // 查询保证金详情
        LogiMarginVo marginVo = queryById(id);
        // 判断保证金的资金状态，如果是正常则不允许操作
        if (marginVo.getFundStatus() == MarginFundStatusEnum.NORMAL.getCode()) {
            throw new GlobalException("请选择资金状态为冻结的保证金作");
        }
        // 修改保证金的资金状态为：正常
        boolean success = update(Wrappers.lambdaUpdate(LogiMargin.class)
                .set(LogiMargin::getFundStatus, MarginFundStatusEnum.NORMAL.getCode())
                .eq(LogiMargin::getId, marginVo.getId()));
        if (!success) {
            throw new GlobalException("解冻保证金失败，请联系管理员");
        }
    }

    @Override
    public List<LogiMarginUserVo> userList(LogiMarginUserQueryBo bo) {
        return getMarginUserList(bo.getDeptId(), null, bo.getUserName(), bo.getUserType());
    }

    /**
     * 组装查询条件
     **/
    private Wrapper<LogiMargin> buildQueryWrapper(LogiMarginQueryBo bo) {
        LambdaQueryWrapper<LogiMargin> lqw = Wrappers.lambdaQuery();
        lqw.eq(LogiMargin::getDeptId, bo.getDeptId());
        lqw.eq(ObjectUtil.isNotNull(bo.getFundStatus()), LogiMargin::getFundStatus, bo.getFundStatus());
        lqw.eq(ObjectUtil.isNotNull(bo.getPayStatus()), LogiMargin::getPayStatus, bo.getPayStatus());
        lqw.between(ObjectUtil.isAllNotEmpty(bo.getCreateStartDate(), bo.getCreateEndDate()), LogiMargin::getCreateTime, bo.getCreateStartDate(), bo.getCreateEndDate());
        // 客户名称筛选
        if (StrUtil.isNotBlank(bo.getUserName())) {
            List<LogiMarginUserVo> marginUserList = getMarginUserList(bo.getDeptId(), null, bo.getUserName(), null);
            if (CollUtil.isNotEmpty(marginUserList)) {
                List<Long> userIds = marginUserList.stream().map(LogiMarginUserVo::getUserId).collect(Collectors.toList());
                lqw.in(LogiMargin::getUserId, userIds);
            } else {
                lqw.isNull(LogiMargin::getId);
            }
        }
        SqlUtil.dataPermissionFilter(lqw, bo.getDeptId());
        return lqw;
    }

    /**
     * 补充字段数据
     **/
    private void fillData(LogiMarginVo a) {
        List<LogiMarginUserVo> marginUserList = getMarginUserList(a.getDeptId(), a.getUserId(), null, a.getUserType());
        if (CollUtil.isNotEmpty(marginUserList)) {
            LogiMarginUserVo marginUserVo = marginUserList.get(0);
            a.setUserName(marginUserVo.getUserName());
            a.setContactPerson(marginUserVo.getContactPerson());
            a.setContactPhone(marginUserVo.getContactPhone());
        }
    }

    /**
     * 获取部门的客户、承运商、司机
     **/
    private List<LogiMarginUserVo> getMarginUserList(Long deptId, Long userId, String userName, Integer userType) {
        List<LogiMarginUserVo> marginUserVoList = CollUtil.newArrayList();
        if (ObjectUtil.isNull(userType) || userType == MarginUserTypeEnum.CUSTOMER.getCode()) {
            marginUserVoList.addAll(logiCustomerService.list(Wrappers.lambdaQuery(LogiCustomer.class)
                            .eq(LogiCustomer::getDeptId, deptId)
                            .eq(ObjectUtil.isNotNull(userId), LogiCustomer::getCustomerId, userId)
                            .like(StrUtil.isNotBlank(userName), LogiCustomer::getCustomerName, userName))
                    .stream().map(a -> {
                        LogiMarginUserVo marginUserVo = new LogiMarginUserVo();
                        marginUserVo.setUserId(a.getCustomerId());
                        marginUserVo.setUserName(a.getCustomerName());
                        marginUserVo.setUserType(MarginUserTypeEnum.CUSTOMER.getCode());
                        marginUserVo.setContactPerson(a.getLeader());
                        marginUserVo.setContactPhone(a.getPhone());
                        return marginUserVo;
                    }).collect(Collectors.toList()));
        }
        if (ObjectUtil.isNull(userType) || userType == MarginUserTypeEnum.CARRIER.getCode()) {
            marginUserVoList.addAll(logiCarrierService.list(Wrappers.lambdaQuery(LogiCarrier.class)
                            .eq(LogiCarrier::getDeptId, deptId)
                            .eq(ObjectUtil.isNotNull(userId), LogiCarrier::getCarrierId, userId)
                            .like(StrUtil.isNotBlank(userName), LogiCarrier::getCarrierName, userName))
                    .stream().map(a -> {
                        LogiMarginUserVo marginUserVo = new LogiMarginUserVo();
                        marginUserVo.setUserId(a.getCarrierId());
                        marginUserVo.setUserName(a.getCarrierName());
                        marginUserVo.setUserType(MarginUserTypeEnum.CARRIER.getCode());
                        marginUserVo.setContactPerson(a.getContactPerson());
                        marginUserVo.setContactPhone(a.getPhone());
                        return marginUserVo;
                    }).collect(Collectors.toList()));
        }
        if (ObjectUtil.isNull(userType) || userType == MarginUserTypeEnum.DRIVER.getCode()) {
            marginUserVoList.addAll(logiCarrierDriverService.list(Wrappers.lambdaQuery(LogiCarrierDriver.class)
                            .eq(LogiCarrierDriver::getDeptId, deptId)
                            .eq(ObjectUtil.isNotNull(userId), LogiCarrierDriver::getDriverId, userId)
                            .like(StrUtil.isNotBlank(userName), LogiCarrierDriver::getDriverName, userName))
                    .stream().map(a -> {
                        LogiMarginUserVo marginUserVo = new LogiMarginUserVo();
                        marginUserVo.setUserId(a.getDriverId());
                        marginUserVo.setUserName(a.getDriverName());
                        marginUserVo.setUserType(MarginUserTypeEnum.DRIVER.getCode());
                        marginUserVo.setContactPerson(a.getDriverName());
                        marginUserVo.setContactPhone(a.getPhoneNumber());
                        return marginUserVo;
                    }).collect(Collectors.toList()));
        }
        return marginUserVoList;
    }
}
